#ifndef FILESYSTEMT_H
#define FILESYSTEMT_H


template <class TFS>
class FileSystemT
{
private:
    static TFS* instance();
    static TFS* iInstance;
public:
    static struct fuse_operations fuse_oper;
public:
    FileSystemT()
    {

//        initoperations();
    };

    static struct fuse_operations& initoperations()
    {


        fuse_oper.getattr	= FileSystemT<TFS>::s_getattr;
        fuse_oper.fgetattr	= FileSystemT<TFS>::s_fgetattr;
        fuse_oper.access		= FileSystemT<TFS>::s_access;
        fuse_oper.readlink	= FileSystemT<TFS>::s_readlink;
        fuse_oper.opendir	= FileSystemT<TFS>::s_opendir;
        fuse_oper.readdir	= FileSystemT<TFS>::s_readdir;
        fuse_oper.releasedir	= FileSystemT<TFS>::s_releasedir;
        fuse_oper.mknod		= FileSystemT<TFS>::s_mknod;
        fuse_oper.mkdir		= FileSystemT<TFS>::s_mkdir;
        fuse_oper.symlink	= FileSystemT<TFS>::s_symlink;
        fuse_oper.unlink		= FileSystemT<TFS>::s_unlink;
        fuse_oper.rmdir		= FileSystemT<TFS>::s_rmdir;
        fuse_oper.rename		= FileSystemT<TFS>::s_rename;
        fuse_oper.link		= FileSystemT<TFS>::s_link;
        fuse_oper.chmod		= FileSystemT<TFS>::s_chmod;
        fuse_oper.chown		= FileSystemT<TFS>::s_chown;
        fuse_oper.truncate	= FileSystemT<TFS>::s_truncate;
        fuse_oper.ftruncate	= FileSystemT<TFS>::s_ftruncate;
        fuse_oper.utimens	= FileSystemT<TFS>::s_utimens;
        fuse_oper.create		= FileSystemT<TFS>::s_create;
        fuse_oper.open		= FileSystemT<TFS>::s_open;
        fuse_oper.read		= FileSystemT<TFS>::s_read;
        fuse_oper.write		= FileSystemT<TFS>::s_write;
        fuse_oper.statfs		= FileSystemT<TFS>::s_statfs;
        fuse_oper.flush		= FileSystemT<TFS>::s_flush;
        fuse_oper.release	= FileSystemT<TFS>::s_release;
        fuse_oper.fsync		= FileSystemT<TFS>::s_fsync;
#ifdef HAVE_SETXATTR
        fuse_oper.setxattr	= FileSystemT<TFS>::s_setxattr;
        fuse_oper.getxattr	= FileSystemT<TFS>::s_getxattr;
        fuse_oper.listxattr	= FileSystemT<TFS>::s_listxattr;
        fuse_oper.removexattr	= FileSystemT<TFS>::s_removexattr;
#endif
        fuse_oper.lock		= FileSystemT<TFS>::s_lock;


        return fuse_oper;
    }


public:
    static int  s_getattr(const char *path, struct stat *stbuf)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_getattr(path , stbuf);
    }

    static int s_fgetattr(const char *path, struct stat *stbuf,
                        struct fuse_file_info *fi)
    {
         if (!iInstance)
            return -errno;
        else
            return iInstance->fs_fgetattr(path , stbuf , fi);

    }



    static int  s_access(const char *path, int mask)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_access(path , mask);
    }

    static int  s_readlink(const char *path, char *buf, size_t size)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_readlink(path , buf , size);

    }

    static int  s_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
                       off_t offset, struct fuse_file_info *fi)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_readdir(path, buf , filler, offset , fi);
    }

    static int s_releasedir(const char *path, struct fuse_file_info *fi)
{
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_releasedir(path , fi);

}

    static int  s_mknod(const char *path, mode_t mode, dev_t rdev)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_mknod(path , mode , rdev);
    }

    static int  s_mkdir(const char *path, mode_t mode)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_mkdir(path , mode);
    }

    static int  s_unlink(const char *path)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_unlink(path);
    }

    static int  s_rmdir(const char *path)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_rmdir(path);
    }

    static int  s_symlink(const char *from, const char *to)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_symlink(from , to);
    }

    static int  s_rename(const char *from, const char *to)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_rename(from ,to);
    }

    static int  s_link(const char *frm, const char *to)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_link(frm , to);
    }

    static int  s_chmod(const char *path, mode_t mode)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_chmod(path , mode);
    }

    static int  s_chown(const char *path, uid_t uid, gid_t gid)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_chown(path , uid , gid);
    }

    static int  s_truncate(const char *path, off_t size)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_truncate(path , size);
    }

    static int s_ftruncate(const char *path, off_t size,
                         struct fuse_file_info *fi)
    {
         if (!iInstance)
            return -errno;
        else
            return iInstance->fs_ftruncate(path , size, fi);

    }

    static int s_opendir(const char *path, struct fuse_file_info *fi)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_opendir(path , fi);

    }


    static int  s_utimens(const char *path, const struct timespec ts[2])
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_utimens(path , ts);
    }

    static int  s_open(const char *path, struct fuse_file_info *fi)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_open(path , fi);
    }

    static int s_create(const char *path, mode_t mode, struct fuse_file_info *fi)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_create(path , mode , fi);

    }

    static int  s_read(const char *path, char *buf, size_t size, off_t offset,
                    struct fuse_file_info *fi)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_read(path , buf, size , offset, fi);
    }

    static int  s_write(const char *path, const char *buf, size_t size,
                     off_t offset, struct fuse_file_info *fi)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_write(path , buf , size, offset , fi);
    }

    static int s_flush(const char *path, struct fuse_file_info *fi)
{
         if (!iInstance)
            return -errno;
        else
            return iInstance->fs_flush(path , fi);

}

    static int  s_statfs(const char *path, struct statvfs *stbuf)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_statfs(path , stbuf);
    }

    static int  s_release(const char *path, struct fuse_file_info *fi)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_release(path , fi);
    }

    static int  s_fsync(const char *path, int isdatasync,
                     struct fuse_file_info *fi)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_fsync(path , isdatasync , fi);
    }


#ifdef HAVE_SETXATTR
    static int  s_setxattr(const char *path, const char *name, const char *value,
                        size_t size, int flags)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_setxattr(path , name , value, size , flags);
    }

    static int  s_getxattr(const char *path, const char *name, char *value,
                        size_t size)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_getxattr(path , name , value , size);
    }

    static int  s_listxattr(const char *path, char *list, size_t size)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_listxattr(path , list, size);
    }

    static int  s_removexattr(const char *path, const char *name)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_removexattr(path , name);
    }

#endif

    static int s_lock(const char *path, struct fuse_file_info *fi, int cmd,
                    struct flock *lock)
    {
        if (!iInstance)
            return -errno;
        else
            return iInstance->fs_lock(path , fi , cmd , lock);
    }

};

template <class TFS>
TFS* FileSystemT<TFS>::iInstance = new TFS/*NULL*/;

template <class TFS>
struct fuse_operations FileSystemT<TFS>::fuse_oper;

#endif // FILESYSTEMT_H
